package com.hospital.workstation.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Console;
import cn.hutool.core.util.ObjectUtil;
import com.hospital.common.core.domain.R;
import com.hospital.common.utils.StringUtils;
import com.hospital.common.core.page.TableDataInfo;
import com.hospital.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.hospital.workstation.domain.MedicalRecord;
import com.hospital.workstation.domain.PatientBaseInfo;
import com.hospital.workstation.domain.vo.MedicalDetailVo;
import com.hospital.workstation.domain.vo.MedicalRecordVo;
import com.hospital.workstation.domain.vo.TimerShaftVo;
import com.hospital.workstation.mapper.PatientBaseInfoMapper;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.map.ListOrderedMap;
import org.aspectj.weaver.ast.Var;
import org.springframework.stereotype.Service;
import com.hospital.workstation.domain.bo.HisMedicalOrdersBo;
import com.hospital.workstation.domain.vo.HisMedicalOrdersVo;
import com.hospital.workstation.domain.HisMedicalOrders;
import com.hospital.workstation.mapper.HisMedicalOrdersMapper;
import com.hospital.workstation.service.IHisMedicalOrdersService;
import org.springframework.web.bind.annotation.PathVariable;

import javax.security.auth.login.Configuration;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 医嘱Service业务层处理
 *
 * @author whb
 * @date 2023-03-10
 */
@RequiredArgsConstructor
@Service
public class HisMedicalOrdersServiceImpl implements IHisMedicalOrdersService {

    private final HisMedicalOrdersMapper baseMapper;
    private final PatientBaseInfoMapper patientBaseInfoMapper;

    /**
     * 查询医嘱
     */
    @Override
    public HisMedicalOrdersVo queryById(Long id) {
        return baseMapper.selectVoById(id);
    }

    /**
     * 查询医嘱列表
     */
    @Override
    public TableDataInfo<HisMedicalOrdersVo> queryPageList(HisMedicalOrdersBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<HisMedicalOrders> lqw = buildQueryWrapper(bo);
        Page<HisMedicalOrdersVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询医嘱列表
     */
    @Override
    public List<HisMedicalOrdersVo> queryList(HisMedicalOrdersBo bo) {
        LambdaQueryWrapper<HisMedicalOrders> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<HisMedicalOrders> buildQueryWrapper(HisMedicalOrdersBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<HisMedicalOrders> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getMedicalRecordNo() != null, HisMedicalOrders::getMedicalRecordNo, bo.getMedicalRecordNo());
        lqw.eq(StringUtils.isNotBlank(bo.getOrderItemId()), HisMedicalOrders::getOrderItemId, bo.getOrderItemId());
        lqw.eq(StringUtils.isNotBlank(bo.getOrderGroupId()), HisMedicalOrders::getOrderGroupId, bo.getOrderGroupId());
        lqw.eq(StringUtils.isNotBlank(bo.getOrderItemCode()), HisMedicalOrders::getOrderItemCode, bo.getOrderItemCode());
        lqw.eq(StringUtils.isNotBlank(bo.getOrderItemDesc()), HisMedicalOrders::getOrderItemDesc, bo.getOrderItemDesc());
        lqw.eq(StringUtils.isNotBlank(bo.getOrderTypeCode()), HisMedicalOrders::getOrderTypeCode, bo.getOrderTypeCode());
        lqw.eq(StringUtils.isNotBlank(bo.getOrderStatus()), HisMedicalOrders::getOrderStatus, bo.getOrderStatus());
        lqw.eq(StringUtils.isNotBlank(bo.getOrderCategory()), HisMedicalOrders::getOrderCategory, bo.getOrderCategory());
        lqw.eq(StringUtils.isNotBlank(bo.getPrescriptionNo()), HisMedicalOrders::getPrescriptionNo, bo.getPrescriptionNo());
        lqw.eq(StringUtils.isNotBlank(bo.getDoseFormsCode()), HisMedicalOrders::getDoseFormsCode, bo.getDoseFormsCode());
        lqw.eq(StringUtils.isNotBlank(bo.getDoseFormsDesc()), HisMedicalOrders::getDoseFormsDesc, bo.getDoseFormsDesc());
        lqw.eq(StringUtils.isNotBlank(bo.getDoseQty()), HisMedicalOrders::getDoseQty, bo.getDoseQty());
        lqw.eq(StringUtils.isNotBlank(bo.getDoseUnitCode()), HisMedicalOrders::getDoseUnitCode, bo.getDoseUnitCode());
        lqw.eq(StringUtils.isNotBlank(bo.getDoseUnitDesc()), HisMedicalOrders::getDoseUnitDesc, bo.getDoseUnitDesc());
        lqw.eq(StringUtils.isNotBlank(bo.getFreqCode()), HisMedicalOrders::getFreqCode, bo.getFreqCode());
        lqw.eq(StringUtils.isNotBlank(bo.getFreqDesc()), HisMedicalOrders::getFreqDesc, bo.getFreqDesc());
        lqw.eq(StringUtils.isNotBlank(bo.getInstrCode()), HisMedicalOrders::getInstrCode, bo.getInstrCode());
        lqw.eq(StringUtils.isNotBlank(bo.getInstrDesc()), HisMedicalOrders::getInstrDesc, bo.getInstrDesc());
        lqw.eq(StringUtils.isNotBlank(bo.getDurationCode()), HisMedicalOrders::getDurationCode, bo.getDurationCode());
        lqw.eq(StringUtils.isNotBlank(bo.getDurationDesc()), HisMedicalOrders::getDurationDesc, bo.getDurationDesc());
        lqw.eq(StringUtils.isNotBlank(bo.getOrderAmount()), HisMedicalOrders::getOrderAmount, bo.getOrderAmount());
        lqw.eq(StringUtils.isNotBlank(bo.getResultStatusCode()), HisMedicalOrders::getResultStatusCode, bo.getResultStatusCode());
        lqw.eq(StringUtils.isNotBlank(bo.getResultStatusDesc()), HisMedicalOrders::getResultStatusDesc, bo.getResultStatusDesc());
        lqw.eq(StringUtils.isNotBlank(bo.getRemarks()), HisMedicalOrders::getRemarks, bo.getRemarks());
        lqw.eq(StringUtils.isNotBlank(bo.getEnterDocCode()), HisMedicalOrders::getEnterDocCode, bo.getEnterDocCode());
        lqw.eq(StringUtils.isNotBlank(bo.getEnterDocDesc()), HisMedicalOrders::getEnterDocDesc, bo.getEnterDocDesc());
        lqw.eq(bo.getEnterTime() != null, HisMedicalOrders::getEnterTime, bo.getEnterTime());
        lqw.eq(StringUtils.isNotBlank(bo.getEnterDeptCode()), HisMedicalOrders::getEnterDeptCode, bo.getEnterDeptCode());
        lqw.eq(StringUtils.isNotBlank(bo.getEnterDeptDesc()), HisMedicalOrders::getEnterDeptDesc, bo.getEnterDeptDesc());
        lqw.eq(StringUtils.isNotBlank(bo.getExecDeptCode()), HisMedicalOrders::getExecDeptCode, bo.getExecDeptCode());
        lqw.eq(StringUtils.isNotBlank(bo.getExecDeptDesc()), HisMedicalOrders::getExecDeptDesc, bo.getExecDeptDesc());
        lqw.eq(bo.getRequireExecTime() != null, HisMedicalOrders::getRequireExecTime, bo.getRequireExecTime());
        lqw.eq(bo.getStopTime() != null, HisMedicalOrders::getStopTime, bo.getStopTime());
        lqw.eq(StringUtils.isNotBlank(bo.getStopDocCode()), HisMedicalOrders::getStopDocCode, bo.getStopDocCode());
        lqw.eq(StringUtils.isNotBlank(bo.getStopDocDesc()), HisMedicalOrders::getStopDocDesc, bo.getStopDocDesc());
        lqw.eq(StringUtils.isNotBlank(bo.getIsSkinTest()), HisMedicalOrders::getIsSkinTest, bo.getIsSkinTest());
        lqw.eq(StringUtils.isNotBlank(bo.getIsEmergency()), HisMedicalOrders::getIsEmergency, bo.getIsEmergency());
        lqw.eq(StringUtils.isNotBlank(bo.getParentOrderId()), HisMedicalOrders::getParentOrderId, bo.getParentOrderId());
        lqw.eq(StringUtils.isNotBlank(bo.getSpecimenId()), HisMedicalOrders::getSpecimenId, bo.getSpecimenId());
        lqw.eq(StringUtils.isNotBlank(bo.getSpecimenCode()), HisMedicalOrders::getSpecimenCode, bo.getSpecimenCode());
        lqw.eq(StringUtils.isNotBlank(bo.getOrderPrice()), HisMedicalOrders::getOrderPrice, bo.getOrderPrice());
        lqw.eq(StringUtils.isNotBlank(bo.getSpeedFlowRate()), HisMedicalOrders::getSpeedFlowRate, bo.getSpeedFlowRate());
        lqw.eq(StringUtils.isNotBlank(bo.getFlowRateUnitDesc()), HisMedicalOrders::getFlowRateUnitDesc, bo.getFlowRateUnitDesc());
        lqw.eq(StringUtils.isNotBlank(bo.getBloodNum()), HisMedicalOrders::getBloodNum, bo.getBloodNum());
        lqw.eq(StringUtils.isNotBlank(bo.getIsPreseCookMode()), HisMedicalOrders::getIsPreseCookMode, bo.getIsPreseCookMode());
        lqw.eq(StringUtils.isNotBlank(bo.getCmPrescCookTypeCode()), HisMedicalOrders::getCmPrescCookTypeCode, bo.getCmPrescCookTypeCode());
        lqw.eq(StringUtils.isNotBlank(bo.getPackUomDesc()), HisMedicalOrders::getPackUomDesc, bo.getPackUomDesc());
        lqw.eq(StringUtils.isNotBlank(bo.getUpdateUserCode()), HisMedicalOrders::getUpdateUserCode, bo.getUpdateUserCode());
        lqw.eq(StringUtils.isNotBlank(bo.getUpdateUserDesc()), HisMedicalOrders::getUpdateUserDesc, bo.getUpdateUserDesc());
        lqw.eq(bo.getUpdateLastTime() != null, HisMedicalOrders::getUpdateLastTime, bo.getUpdateLastTime());
        return lqw;
    }

    /**
     * 新增医嘱
     */
    @Override
    public Boolean insertByBo(HisMedicalOrdersBo bo) {
        HisMedicalOrders add = BeanUtil.toBean(bo, HisMedicalOrders.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改医嘱
     */
    @Override
    public Boolean updateByBo(HisMedicalOrdersBo bo) {
        HisMedicalOrders update = BeanUtil.toBean(bo, HisMedicalOrders.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(HisMedicalOrders entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除医嘱
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    /**
     * 查询HIS医嘱用药列表
     *
     * @param medicalRecordNo 药历号
     * @return
     */
    @Override
    public R<List<MedicalRecordVo>> queryListByMedicalRecordNo(Integer medicalRecordNo) {
        return R.ok(baseMapper.selectListByMedicalRecordNo(medicalRecordNo));
    }

    /**
     * 查询HIS医嘱用药列表（分组）
     *
     * @param medicalRecordNo 病历号
     * @param category        类别（1长嘱 2临嘱 3中药饮片）
     * @return
     */
    @Override
    public R<List<MedicalRecordVo>> queryOrdersListToGroup(Integer medicalRecordNo, String category) {
        String condition = null; // 查询字段
        List<String> categoryList = new ArrayList<>();
        boolean isHaveTraditional = true; // 是否包含中药饮片（不为空时不查询）
        if ("1".equals(category)) {
            categoryList.add("自备药长期");
            categoryList.add("长期医嘱");
            categoryList.add("长期嘱托");
            condition = "order_type_code";
        } else if ("2".equals(category)) {
            categoryList.add("临时医嘱");
            categoryList.add("临时嘱托");
            categoryList.add("出院带药");
            categoryList.add("取药医嘱");
            categoryList.add("自备药即刻");
            condition = "order_type_code";
        } else if ("3".equals(category)) {
            categoryList.add("中药饮片");
            condition = "order_category";
            isHaveTraditional = false;
        } else {
            return R.ok("类别有误");
        }
        List<MedicalRecordVo> medicalRecordVoList = baseMapper.selectOrdersListToGroup2(medicalRecordNo, condition, categoryList, isHaveTraditional);
        if (medicalRecordVoList.size() == 0) {
            return R.ok("暂无数据");
        }
        List<MedicalRecordVo> returnMedicalRecordVoList = new ArrayList<>();
        // 先过滤出主医嘱和没有子医嘱的列表
        returnMedicalRecordVoList = medicalRecordVoList.stream().filter(medicalRecordVo -> "".equals(medicalRecordVo.getOrderGroupId())).collect(Collectors.toList());
        // 为主医嘱封装子医嘱
        returnMedicalRecordVoList.stream().forEach(medicalRecordVo -> {
            List<MedicalRecordVo> childMedicalRecordVoList = new ArrayList<>();
            medicalRecordVoList.stream().forEach(medicalRecordVo2 -> {
                if (medicalRecordVo.getOrderItemId().equals(medicalRecordVo2.getOrderGroupId())) {
                    childMedicalRecordVoList.add(medicalRecordVo2);
                }
            });
            medicalRecordVo.setChildMedicalRecordList(childMedicalRecordVoList);
        });
        return R.ok("查询成功", returnMedicalRecordVoList);
    }

    /**
     * 查询患者医嘱用药信息
     *
     * @param medicalRecordNo 病历号
     * @param orderCategory   医嘱类别（1西药 2中成药 3中药饮片）
     * @return
     */
    @Override
    public R<TimerShaftVo> queryTimerShaft(Integer medicalRecordNo, String orderCategory) {
        // 判断医嘱类型
        if ("1".equals(orderCategory)) {
            orderCategory = "西药";
        } else if ("2".equals(orderCategory)) {
            orderCategory = "中成药";
        } else if ("3".equals(orderCategory)) {
            orderCategory = "中药饮片";
        } else {
            return R.ok("暂无数据");
        }
        // 查询患者医嘱用药药物列表
        // List<String> orderItemList = baseMapper.selectOrderItemDescList(medicalRecordNo, orderCategory);
        List<HisMedicalOrdersVo> ordersVoList = baseMapper.selectOrderItemDescList2(medicalRecordNo, orderCategory);
        // 还没有用药
        /*if (orderItemList.size() == 0) {
            return R.ok("暂无数据");
        }*/
        if (ordersVoList.size() == 0) {
            return R.ok("暂无数据");
        }
        // 计算住院的时间
        // 查询患者住院信息
        int inHospitalDays = 0;
        PatientBaseInfo patientBaseInfo = patientBaseInfoMapper.selectOne(new LambdaQueryWrapper<PatientBaseInfo>().eq(PatientBaseInfo::getMedicalRecordNo, medicalRecordNo));
        // 入院时间
        LocalDateTime admissionTime = patientBaseInfo.getAdmissionTime();
        // 出院时间
        LocalDateTime dischargeTime = patientBaseInfo.getDischargeTime();
        // 现在时间
        LocalDateTime nowTime = LocalDateTime.now();
        if (ObjectUtil.isNull(dischargeTime)) { // 住院
            inHospitalDays = (int) (nowTime.toLocalDate().toEpochDay() - admissionTime.toLocalDate().toEpochDay());
        } else { // 出院
            inHospitalDays = (int) (dischargeTime.toLocalDate().toEpochDay() - admissionTime.toLocalDate().toEpochDay());
        }
        // 住院第二天开始算
        if (inHospitalDays > 0) {
            // 住院天数
            final int inDays = inHospitalDays;
            // 查询医嘱用药列表
            List<HisMedicalOrdersVo> medicalOrdersVoList = baseMapper.selectVoList(new LambdaQueryWrapper<HisMedicalOrders>()
                //.likeRight(HisMedicalOrders::getOrderTypeCode, "长期")
                //.eq(HisMedicalOrders::getOrderCategory, "西药")
                .eq(HisMedicalOrders::getOrderCategory, orderCategory)
                //.ne(HisMedicalOrders::getDoseFormsCode, "注射液")
                .eq(HisMedicalOrders::getMedicalRecordNo, medicalRecordNo));
            // 创建用药时间轴视图对象
            TimerShaftVo timerShaftVo = new TimerShaftVo();
            timerShaftVo.setInHospitalDays(inHospitalDays);
            // 创建用药详情map
            // Map<String, List<MedicalDetailVo>> map = new HashMap<>();
            Map<String, List<MedicalDetailVo>> map = new TreeMap<>();
            // for (String orderItemDesc : orderItemList) {
            for (HisMedicalOrdersVo OrdersVo : ordersVoList) {
                List<MedicalDetailVo> list = new ArrayList<>();
                // 当前药物明细列表
                List<HisMedicalOrdersVo> currentOrderList = medicalOrdersVoList.stream().filter(hisMedicalOrdersVo -> OrdersVo.getOrderItemDesc().equals(hisMedicalOrdersVo.getOrderItemDesc())
                    && OrdersVo.getDoseQty().equals(hisMedicalOrdersVo.getDoseQty())
                    && OrdersVo.getFreqCode().equals(hisMedicalOrdersVo.getFreqCode())
                    && OrdersVo.getInstrCode().equals(hisMedicalOrdersVo.getInstrCode())
                    && !hisMedicalOrdersVo.getRequireExecTime().toLocalDate().isAfter(nowTime.toLocalDate()))
                    .sorted(Comparator.comparing(HisMedicalOrdersVo::getRequireExecTime))
                    .collect(Collectors.toList());
                // 封装用药详情情况
                currentOrderList.stream().forEach(hisMedicalOrdersVo -> {
                    // 创建用药详情视图对象
                    MedicalDetailVo medicalDetailVo = new MedicalDetailVo();
                    // 要求执行时间
                    LocalDateTime requireExecTime = hisMedicalOrdersVo.getRequireExecTime();
                    // 医嘱停止时间
                    LocalDateTime stopTime = hisMedicalOrdersVo.getStopTime();
                    if (ObjectUtil.isNotNull(stopTime)) { // 医嘱有停止时间
                        if (stopTime.toLocalDate().isBefore(nowTime.toLocalDate()) || stopTime.toLocalDate().isEqual(nowTime.toLocalDate())) { // 医嘱结束日期在当前日期之前
                            // 开始天数
                            medicalDetailVo.setBeginDay((int) (requireExecTime.toLocalDate().toEpochDay() - admissionTime.toLocalDate().toEpochDay()) != 0 ? (int) (requireExecTime.toLocalDate().toEpochDay() - admissionTime.toLocalDate().toEpochDay()) : 1);
                            // 结束天数
                            // medicalDetailVo.setEndDay((int) (stopTime.toLocalDate().toEpochDay() - admissionTime.toLocalDate().toEpochDay()) != 0 ? (int) (stopTime.toLocalDate().toEpochDay() - admissionTime.toLocalDate().toEpochDay()) : 1);
                            Integer days = 1; // 用药天数
                            String durationCode = hisMedicalOrdersVo.getDurationCode(); // 疗程
                            if (StringUtils.isNotBlank(durationCode)) {
                                if (durationCode.contains("天")) {
                                    days = Integer.valueOf(durationCode.split("天")[0]);
                                } else if (durationCode.contains("付")) {
                                    days = Integer.valueOf(durationCode.split("付")[0]);
                                }
                            }
                            if (days > 1) {
                                medicalDetailVo.setEndDay(medicalDetailVo.getBeginDay() + (days - 1));
                            } else {
                                medicalDetailVo.setEndDay(medicalDetailVo.getBeginDay());
                            }

                        } else { // 医嘱结束日期在当前日期之后
                            // 开始天数
                            medicalDetailVo.setBeginDay((int) (requireExecTime.toLocalDate().toEpochDay() - admissionTime.toLocalDate().toEpochDay()) != 0 ? (int) (requireExecTime.toLocalDate().toEpochDay() - admissionTime.toLocalDate().toEpochDay()) : 1);
                            // 结束天数
                            // medicalDetailVo.setEndDay((int) (nowTime.toLocalDate().toEpochDay() - admissionTime.toLocalDate().toEpochDay()));
                            medicalDetailVo.setEndDay(inDays);
                        }
                    } else { // 医嘱没有停止时间
                        // 开始天数
                        medicalDetailVo.setBeginDay((int) (requireExecTime.toLocalDate().toEpochDay() - admissionTime.toLocalDate().toEpochDay()) != 0 ? (int) (requireExecTime.toLocalDate().toEpochDay() - admissionTime.toLocalDate().toEpochDay()) : 1);
                        // 结束天数
                        medicalDetailVo.setEndDay((int) (nowTime.toLocalDate().toEpochDay() - admissionTime.toLocalDate().toEpochDay()));
                    }
                    // 用法用量
                    medicalDetailVo.setUsageAndDosage(hisMedicalOrdersVo.getDoseQty() + hisMedicalOrdersVo.getDoseUnitCode()
                        + " " + hisMedicalOrdersVo.getInstrCode()
                        + " " + hisMedicalOrdersVo.getFreqCode());
                    list.add(medicalDetailVo);
                });

                // 设置间隔数
                if (list.size() > 1) {
                    for (int i = 0; i < list.size(); i++) {
                        // 从第二个开始计算间隔数
                        if (i < list.size() - 1) {
                            list.get(i).setTime((list.get(i + 1).getBeginDay() - list.get(i).getEndDay()) - 1);
                        }
                    }
                }
                map.put(OrdersVo.getOrderItemDesc() + "-" + OrdersVo.getFreqCode() + "-" + OrdersVo.getInstrCode(), list);
            }
            timerShaftVo.setMedicalDetailMap(map);
            return R.ok("查询成功", timerShaftVo);
        }
        return R.ok("暂无数据");
    }

    /**
     * 根据医嘱明细Id查询医嘱
     *
     * @param orderItemID 医嘱明细Id
     * @return
     */
    @Override
    public HisMedicalOrders queryByOrderItemId(String orderItemID) {
        return baseMapper.selectOne(new LambdaQueryWrapper<HisMedicalOrders>().eq(HisMedicalOrders::getOrderItemId, orderItemID));
    }

    /**
     * 分组显示用药时间轴数据
     *
     * @param medicalRecordNo 病历号
     * @param category        类别（1长嘱 2临嘱 3中药饮片）
     * @return
     */
    @Override
    public R<TimerShaftVo> queryTimerShaftShowGroup(Integer medicalRecordNo, String category) {
        // 查询患者医嘱用药列表
        LambdaQueryWrapper<HisMedicalOrders> lqw = new LambdaQueryWrapper<>();
        if ("1".equals(category)) { // 长嘱
            lqw.in(HisMedicalOrders::getOrderTypeCode, "自备药长期", "长期医嘱", "长期嘱托")
                .notIn(HisMedicalOrders::getOrderCategory, "护理", "中药饮片");
        } else if ("2".equals(category)) {
            lqw.in(HisMedicalOrders::getOrderTypeCode, "临时医嘱", "临时嘱托", "出院带药", "取药医嘱", "自备药即刻")
                .notIn(HisMedicalOrders::getOrderCategory, "护理", "中药饮片");
        } else if ("3".equals(category)) { // 中药饮片
            lqw.eq(HisMedicalOrders::getOrderCategory, "中药饮片");
        } else {
            return R.ok("类别有误");
        }
        lqw.eq(HisMedicalOrders::getMedicalRecordNo, medicalRecordNo); //药历号
        lqw.orderByAsc(HisMedicalOrders::getId); // 根据ID顺序排列
        lqw.select(HisMedicalOrders::getOrderItemId, HisMedicalOrders::getOrderGroupId,
            HisMedicalOrders::getOrderItemDesc, HisMedicalOrders::getFreqCode,
            HisMedicalOrders::getDoseQty, HisMedicalOrders::getDoseUnitCode,
            HisMedicalOrders::getInstrCode, HisMedicalOrders::getDurationCode,
            HisMedicalOrders::getRequireExecTime, HisMedicalOrders::getStopTime);
        List<HisMedicalOrdersVo> ordersVoList = baseMapper.selectVoList(lqw);
        if (ObjectUtil.isNotNull(ordersVoList) && ordersVoList.size() == 0) {
            return R.ok("暂无数据");
        }
        // 计算住院的时间
        // 查询患者住院信息
        int inHospitalDays = 0;
        PatientBaseInfo patientBaseInfo = patientBaseInfoMapper.selectOne(new LambdaQueryWrapper<PatientBaseInfo>().eq(PatientBaseInfo::getMedicalRecordNo, medicalRecordNo));
        // 入院时间
        LocalDateTime admissionTime = patientBaseInfo.getAdmissionTime();
        // 出院时间
        LocalDateTime dischargeTime = patientBaseInfo.getDischargeTime();
        // 现在时间
        LocalDateTime nowTime = LocalDateTime.now();
        if (ObjectUtil.isNull(dischargeTime)) { // 住院
            inHospitalDays = (int) (nowTime.toLocalDate().toEpochDay() - admissionTime.toLocalDate().toEpochDay()) + 1;
        } else { // 出院
            inHospitalDays = (int) (dischargeTime.toLocalDate().toEpochDay() - admissionTime.toLocalDate().toEpochDay()) + 1;
        }
        // 住院第二天开始算
        if (inHospitalDays > 0) {
            // 住院天数
            final int inDays = inHospitalDays;
            // 创建用药时间轴视图对象
            TimerShaftVo timerShaftVo = new TimerShaftVo();
            timerShaftVo.setInHospitalDays(inHospitalDays);
            // 创建用药详情map
            // Map<String, List<MedicalDetailVo>> map = new TreeMap<>();
            Map<String, List<MedicalDetailVo>> map = new ListOrderedMap<>();
            for (HisMedicalOrdersVo OrdersVo : ordersVoList) {
                List<MedicalDetailVo> list = new ArrayList<>();
                // 创建用药详情视图对象
                MedicalDetailVo medicalDetailVo = new MedicalDetailVo();
                // 要求执行时间
                LocalDateTime requireExecTime = OrdersVo.getRequireExecTime();
                // 医嘱停止时间
                LocalDateTime stopTime = OrdersVo.getStopTime();
                if (ObjectUtil.isNotNull(stopTime)) { // 医嘱有停止时间
                    if (stopTime.toLocalDate().isBefore(nowTime.toLocalDate()) || stopTime.toLocalDate().isEqual(nowTime.toLocalDate())) { // 医嘱结束日期在当前日期之前
                        // 开始天数
                        medicalDetailVo.setBeginDay((int) (requireExecTime.toLocalDate().toEpochDay() - admissionTime.toLocalDate().toEpochDay()) != 0 ? (int) (requireExecTime.toLocalDate().toEpochDay() - admissionTime.toLocalDate().toEpochDay()) + 1 : 1);
                        // 结束天数
                        if (StringUtils.equals(category, "1")) { // 长嘱
                            medicalDetailVo.setEndDay((int) (stopTime.toLocalDate().toEpochDay() - admissionTime.toLocalDate().toEpochDay()) != 0 ? (int) (stopTime.toLocalDate().toEpochDay() - admissionTime.toLocalDate().toEpochDay()) + 1 : 1);
                        } else { // 临嘱和中药饮片
                            Integer days = 1; // 用药天数
                            String durationCode = OrdersVo.getDurationCode(); // 疗程
                            if (StringUtils.isNotBlank(durationCode)) {
                                if (durationCode.contains("天")) {
                                    days = Integer.valueOf(durationCode.split("天")[0]);
                                } else if (durationCode.contains("付")) {
                                    days = Integer.valueOf(durationCode.split("付")[0]);
                                }
                            }
                            if (days > 1) {
                                medicalDetailVo.setEndDay(medicalDetailVo.getBeginDay() + (days - 1));
                            } else {
                                medicalDetailVo.setEndDay(medicalDetailVo.getBeginDay());
                            }
                        }
                    } else { // 医嘱结束日期在当前日期之后
                        // 开始天数
                        medicalDetailVo.setBeginDay((int) (requireExecTime.toLocalDate().toEpochDay() - admissionTime.toLocalDate().toEpochDay()) != 0 ? (int) (requireExecTime.toLocalDate().toEpochDay() - admissionTime.toLocalDate().toEpochDay()) + 1 : 1);
                        // 结束天数
                        // medicalDetailVo.setEndDay((int) (nowTime.toLocalDate().toEpochDay() - admissionTime.toLocalDate().toEpochDay()));
                        medicalDetailVo.setEndDay(inDays);
                    }
                } else { // 医嘱没有停止时间
                    // 开始天数
                    medicalDetailVo.setBeginDay((int) (requireExecTime.toLocalDate().toEpochDay() - admissionTime.toLocalDate().toEpochDay()) != 0 ? (int) (requireExecTime.toLocalDate().toEpochDay() - admissionTime.toLocalDate().toEpochDay()) + 1 : 1);
                    // 结束天数
                    medicalDetailVo.setEndDay((int) (nowTime.toLocalDate().toEpochDay() - admissionTime.toLocalDate().toEpochDay()) + 1);
                }
                // 用法用量
                medicalDetailVo.setUsageAndDosage(OrdersVo.getDoseQty() + OrdersVo.getDoseUnitCode()
                    + " " + OrdersVo.getInstrCode()
                    + " " + OrdersVo.getFreqCode());
                // 查询分组数量
                List<HisMedicalOrdersVo> collect = ordersVoList.stream().filter(hisMedicalOrdersVo -> OrdersVo.getOrderItemId().equals(hisMedicalOrdersVo.getOrderGroupId()))
                    .collect(Collectors.toList());
                medicalDetailVo.setXHeight(collect.size());
                // 颜色
                // medicalDetailVo.setColor("#92DDE3"); // #92DDE3 #E9F4D8
                list.add(medicalDetailVo);
                map.put(OrdersVo.getOrderItemDesc() + "~" + OrdersVo.getFreqCode() + "~" + OrdersVo.getInstrCode() + "~" + OrdersVo.getOrderItemId() + "~" + OrdersVo.getOrderGroupId(), list);
            }

            // 设置主医嘱背景色
            int i = 1;
            for (String key : map.keySet()) {
                List<MedicalDetailVo> medicalDetailVoList = map.get(key);
                MedicalDetailVo medicalDetailVo = medicalDetailVoList.get(0);
                int xHeight = medicalDetailVo.getXHeight();
                if (xHeight > 0) {
                    if (i % 2 == 0) {
                        medicalDetailVo.setColor("#92DDE3");
                    } else {
                        medicalDetailVo.setColor("#E9F4D8");
                    }
                    i++;
                }
            }
            // 查询主医嘱和背景色
            List<Map<String, String>> masterAndColorList = new ArrayList<>();
            map.forEach((k, v) -> {
                List<MedicalDetailVo> medicalDetailVoList = v;
                MedicalDetailVo medicalDetailVo = medicalDetailVoList.get(0);
                if (medicalDetailVo.getXHeight() > 0 && StringUtils.isNotBlank(medicalDetailVo.getColor())) {
                    Map<String, String> masterAndColorMap = new ListOrderedMap<>();
                    masterAndColorMap.put("color", medicalDetailVo.getColor()); // 主医嘱背景色
                    masterAndColorMap.put("masterId", k.split("~")[3]);
                    masterAndColorList.add(masterAndColorMap);
                }
            });
            // 设置子医嘱背景色
            masterAndColorList.stream().forEach(masterAndColorMap -> {
                String color = masterAndColorMap.get("color");
                String masterId = masterAndColorMap.get("masterId");
                // 遍历医嘱
                map.forEach((k, v) -> {
                    List<MedicalDetailVo> medicalDetailVoList = v;
                    MedicalDetailVo medicalDetailVo = medicalDetailVoList.get(0);
                    String[] split = k.split("~");
                    if (split.length == 5) {
                        String groupId = split[4];
                        if (StringUtils.isNotBlank(groupId)) {
                            if (groupId.equals(masterId)) {
                                medicalDetailVo.setColor(color);
                            }
                        }
                    }
                });
            });
            timerShaftVo.setMedicalDetailMap(map);
            // 中药饮片分组
            if ("3".equals(category)) {
                // 获取中药饮片组id
                List<String> groupIdList = new ArrayList<>();
                map.forEach((k, v) -> {
                    MedicalDetailVo medicalDetailVo = v.get(0);
                    if (medicalDetailVo.getXHeight() > 0) {
                        String[] split = k.split("~");
                        groupIdList.add(split[3]);
                    }
                });
                // 根据中药饮片组id进行过滤
                List<MedicalDetailVo> traditionalGroupList = new ArrayList<>();
                if (groupIdList.size() > 0) { // 有主医嘱和子医嘱
                    groupIdList.stream().forEach(groupId -> {
                        MedicalDetailVo medicalDetailVo = new MedicalDetailVo();
                        List<String> pillsNameList = new ArrayList<>();
                        map.forEach((k, v) -> {
                            String[] split = k.split("~");
                            String[] usageSplit = v.get(0).getUsageAndDosage().split(" ");
                            if (split.length == 4 && split[3].equals(groupId)) {
                                medicalDetailVo.setBeginDay(v.get(0).getBeginDay());
                                medicalDetailVo.setEndDay(v.get(0).getEndDay());
                                medicalDetailVo.setColor(v.get(0).getColor());
                                medicalDetailVo.setUsageAndDosage(usageSplit[1] + " " + usageSplit[2] + " " + usageSplit[3]);
                                pillsNameList.add(split[0] + " " + usageSplit[0]);
                            } else if (split.length == 5 && split[4].equals(groupId)) {
                                pillsNameList.add(split[0] + " " + usageSplit[0]);
                            }
                        });
                        medicalDetailVo.setPillsNameList(pillsNameList);
                        traditionalGroupList.add(medicalDetailVo);
                    });
                } else { // 没有子医嘱
                    map.forEach((k1, v1) -> {
                        MedicalDetailVo medicalDetailNoGroupVo = new MedicalDetailVo();
                        List<String> pillsNameList = new ArrayList<>();
                        String[] split = k1.split("~");
                        String[] usageSplit = v1.get(0).getUsageAndDosage().split(" ");
                        if (split.length == 4) {
                            medicalDetailNoGroupVo.setBeginDay(v1.get(0).getBeginDay());
                            medicalDetailNoGroupVo.setEndDay(v1.get(0).getEndDay());
                            medicalDetailNoGroupVo.setUsageAndDosage(usageSplit[1] + " " + usageSplit[2] + " " + usageSplit[3]);
                            pillsNameList.add(split[0] + " " + usageSplit[0]);
                        }
                        medicalDetailNoGroupVo.setPillsNameList(pillsNameList);
                        traditionalGroupList.add(medicalDetailNoGroupVo);
                    });
                }
                timerShaftVo.setTraditionalGroupList(traditionalGroupList);
            }
            return R.ok("查询成功", timerShaftVo);
        }
        return R.ok("暂无数据");
    }
}
